package com.iob.coin.covid19kg.naturallanguage;


import com.iob.coin.config.MainConfig;
import com.iob.coin.covid19kg.exceptions.QuestionTreeException;
import com.iob.coin.entity.questionTree.LabelTree;
import com.iob.coin.entity.questionTree.QuestionTree;
import com.iob.coin.entity.questionTree.TripleTree;
import org.fnlp.util.exception.LoadModelException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.fnlp.nlp.cn.CNFactory;
import org.fnlp.nlp.parser.dep.DependencyTree;

import java.io.File;
import java.util.ArrayList;

import java.util.ArrayList;

/**
 * @Author: GuoXinyuan
 * @Date: 2021/5/29
 * 负责将自然语言处理为程序可理解的三元组
 */

@Component
public class NaturalLanguageResolver {

    /**
     * 解析一个句子得到一个三元组
     * @param question
     * @return
     */
    private CNFactory factory;

    {
        try {
            factory = CNFactory.getInstance(MainConfig.LANGUAGE_MODEL_PATH);
//            factory = CNFactory.getInstance(File.separator+"home"+File.separator+"lighthouse"+File.separator+"ftp"+File.separator+"backend-coin"
//                    + File.separator + "models");
        } catch (LoadModelException e) {
            e.printStackTrace();
        }
    }

    private QuestionTree resolveForTest(){
        try {
            QuestionTree t1 = new TripleTree(
                    new LabelTree("变态"),
                    new LabelTree("相关疾病"),
                    null
            );
            QuestionTree t2 = new TripleTree(
                    t1,
                    new LabelTree("症状"),
                    null
            );
            return t2;
        }catch (QuestionTreeException questionTreeException){
            questionTreeException.printStackTrace();
        }
        return null;
    }

    /**
     * 将自然语言问题解析为问题树
     * @param question
     * @return
     * @throws QuestionTreeException ！！！发生此异常意味着不合法的问题树被构建 不能内部解决 直接导致本次操作失败返回
     */
    public QuestionTree resolve(String question) throws QuestionTreeException {

        //todo 测试用
//        if(true)return resolveForTest();

        // 创建中文处理工厂对象，并使用“models”目录下的模型文件初始化

        //精神过敏的相关疾病的症状是什么
        // 使用分词器对中文句子进行分词，得到分词结果
        DependencyTree root = factory.parse2T(question);
        String[] tempList=root.toString().split("\n");
        ArrayList<String []> wordsMatrix=new ArrayList<>();
        for(int i=0;i<tempList.length;i++){
            wordsMatrix.add(tempList[i].split(" "));
        }
        ArrayList<String> nouns_before=new ArrayList<>();
        getNouns(root,nouns_before);
        ArrayList<String> nouns=new ArrayList<>();
        for(int i=0;i<nouns_before.size();i++){
            boolean ifIn=false;
            for(int j=0;j<nouns_before.size();j++){
                if(j!=i && nouns_before.get(j).contains(nouns_before.get(i))){
                    ifIn=true;
                    break;
                }
            }
            if(!ifIn) nouns.add(nouns_before.get(i));
        }
        if(nouns.size()==0){
            return null;
        }
        else if(nouns.size()==1){
            return new LabelTree(nouns.get(0));
        }
        else{
            if(question.substring(0,2).equals("什么")||wordsMatrix.size()>0 && wordsMatrix.get(0)[2].equals("疑问代词")){
//        TripleTree answerNode = new TripleTree(null, new LabelTree(nouns.get(0)),null);
                if(nouns.size()>=3){
                    QuestionTree answer=new TripleTree(null,new LabelTree(nouns.get(1)),new LabelTree(nouns.get(0)));;
                    for(int i=2;i<nouns.size();i++){
                        answer=new TripleTree(null,new LabelTree(nouns.get(i)),answer);
                    }
                    return answer;
//            TripleTree sonNode=new TripleTree(new LabelTree(nouns.get(2)),new LabelTree(nouns.get(1)),null);
//            return new TripleTree(sonNode,new LabelTree(nouns.get(0)),null);
//            answerNode.setSubject(sonNode);
                }
                else if(nouns.size()==2){
                    return new TripleTree(null,new LabelTree(nouns.get(1)),new LabelTree(nouns.get(0)));
//            answerNode.setSubject(new LabelTree(nouns.get(1)));
                }

            }
            else{

//        TripleTree answerNode = new TripleTree(null, new LabelTree(nouns.get(0)),null);
                if(nouns.size()>=3){
                    QuestionTree answer=new TripleTree(new LabelTree(nouns.get(nouns.size()-1)),new LabelTree(nouns.get(nouns.size()-2)),null);;
                    for(int i=nouns.size()-3;i>=0;i--){
                        answer=new TripleTree(answer,new LabelTree(nouns.get(i)),null);
                    }
                    return answer;
//            TripleTree sonNode=new TripleTree(new LabelTree(nouns.get(2)),new LabelTree(nouns.get(1)),null);
//            return new TripleTree(sonNode,new LabelTree(nouns.get(0)),null);
//            answerNode.setSubject(sonNode);
                }
                else if(nouns.size()==2){
                    return new TripleTree(new LabelTree(nouns.get(1)),new LabelTree(nouns.get(0)),null);
//            answerNode.setSubject(new LabelTree(nouns.get(1)));
                }
            }
        }



        throw new QuestionTreeException();

//        try {
//            TripleTree t = new TripleTree(new LabelTree("变态"),null,null);
//            TripleTree tripleTree1 = new TripleTree(
//                    new LabelTree("变态"),
//                    new LabelTree("相关疾病"),
//                    null
//            );
//
//            TripleTree tripleTree2 = new TripleTree(
//                    tripleTree1,
//                    new LabelTree("临床症状"),
//                    null
//            );
//            return t;
//
//        }catch (QuestionTreeException e){
//            e.printStackTrace();
//            return null;
//        }

    }

    //    private QuestionTree generateAnswerTree(ArrayList<String> nouns,int i){
//        if(i==0){
//            return new LabelTree(nouns.get(0));
//        }
//        else {
//            return new TripleTree(new LabelTree(nouns.get(1)),new LabelTree(nouns.get(0)),null);
//        }
//    }
    private static void getNouns(DependencyTree node, ArrayList<String> answer){
        if(node.pos.equals("名词") || node.pos.equals("形谓词")){
            String tmp_ans=node.word;

            if(node.getParent()!=null){
                DependencyTree tmp_node=node.getParent();
                if(tmp_node.pos.equals("形容词") || tmp_node.pos.equals("形谓词") || tmp_node.pos.equals("名词") || tmp_node.pos.equals("副词")|| (tmp_node.relation!=null&&tmp_node.relation.equals("补语")&&tmp_node.word.length()>1)){
                    if(tmp_node.id>node.id){
                        tmp_ans+=tmp_node.word;
                    }
                    else{
                        tmp_ans=tmp_node.word+tmp_ans;
                    }
                }
            }

            for(int i=node.rightChilds.size()-1;i>=0;i--){
                DependencyTree tmp_node=node.rightChilds.get(i);
                if(tmp_node.pos.equals("形谓词") || tmp_node.pos.equals("形容词") || tmp_node.pos.equals("名词") || tmp_node.pos.equals("副词")|| (tmp_node.relation!=null&&tmp_node.relation.equals("补语")&&tmp_node.word.length()>1)){
                    if(tmp_node.id>node.id){
                        tmp_ans+=tmp_node.word;
                    }
                    else{
                        tmp_ans=tmp_node.word+tmp_ans;
                    }
                }
            }

            for(int i=node.leftChilds.size()-1;i>=0;i--){
                DependencyTree tmp_node=node.leftChilds.get(i);
                if(tmp_node.pos.equals("形容词") || tmp_node.pos.equals("形谓词") || tmp_node.pos.equals("名词") || tmp_node.pos.equals("副词")|| (tmp_node.relation!=null&&tmp_node.relation.equals("补语")&&tmp_node.word.length()>1)){
                    if(tmp_node.id>node.id){
                        tmp_ans+=tmp_node.word;
                    }
                    else{
                        tmp_ans=tmp_node.word+tmp_ans;
                    }
                }
            }


            boolean isIn=false;
            for(int i=0;i<answer.size();i++){
                if(answer.get(i).equals(tmp_ans)){
                    isIn=true;
                    break;
                }
            }
            if(! isIn) answer.add(tmp_ans);

        }
        if(node.rightChilds.size()!=0){
            for(int i=node.rightChilds.size()-1;i>=0;i--){
                getNouns(node.rightChilds.get(i),answer);
            }
        }

        if(node.leftChilds.size()!=0){
            for(int i=node.leftChilds.size()-1;i>=0;i--){
                getNouns(node.leftChilds.get(i),answer);
            }
        }

    }

//    public static void main(String[] args) throws Exception {
//        //什么的多发人群是小于50岁者？
//        NaturalLanguageResolver resolver =new NaturalLanguageResolver();
//        QuestionTree answer=resolver.resolve("小儿感冒颗粒的药品类型");
//        System.out.println();
//
//
//
//    }
}



